package com.example.smartwaterapi.controller;

import com.example.smartwaterapi.common.api.RestApiResponse;
import com.example.smartwaterapi.common.api.ResultCode;
import com.example.smartwaterapi.service.WechatService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
import jakarta.servlet.http.HttpServletRequest;
import com.example.smartwaterapi.common.exception.ApiException;
import com.example.smartwaterapi.entity.User;
import com.example.smartwaterapi.service.UserService;
import cn.binarywang.wx.miniapp.api.WxMaService;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import com.example.smartwaterapi.security.SecurityUser;
import java.util.HashMap;

/**
 * 微信相关接口控制器
 */
@Slf4j
@Tag(name = "微信API", description = "微信登录和账号绑定相关接口")
@RestController
@RequestMapping("/api/wechat")
public class WechatController {

    @Autowired
    private WechatService wechatService;

    @Autowired
    private UserService userService;

    @Autowired
    private WxMaService wxMaService;

    /**
     * 微信登录接口
     * @param code 微信登录code，支持从URL参数、请求头或请求体获取
     * @return 登录结果
     */
    @Operation(summary = "微信登录", description = "使用微信授权码登录，支持从URL参数、请求头或请求体获取code")
    @PostMapping("/login")
    public RestApiResponse<Map<String, Object>> login(
            @Parameter(description = "微信授权码") @RequestParam(required = false) String code,
            @Parameter(description = "微信授权码") @RequestHeader(value = "X-Wechat-Code", required = false) String headerCode,
            @Parameter(description = "用户信息") @RequestBody(required = false) Map<String, Object> userInfo) {
        
        log.info("微信登录请求 - URL参数code: {}", code);
        log.info("微信登录请求 - 请求头code: {}", headerCode);
        log.info("微信登录请求 - 请求体: {}", userInfo);
        
        // 优先使用请求头中的code
        if (StringUtils.hasText(headerCode)) {
            log.info("使用请求头中的微信code");
            code = headerCode;
        } else if (userInfo != null && userInfo.containsKey("wxCode")) {
            log.info("使用请求体中的微信code");
            code = userInfo.get("wxCode").toString();
        }
        
        // 提取用户信息
        String nickname = null;
        String avatar = null;
        Integer gender = null;
        
        if (userInfo != null) {
            if (userInfo.containsKey("nickname")) {
                nickname = userInfo.get("nickname").toString();
            }
            if (userInfo.containsKey("avatar")) {
                avatar = userInfo.get("avatar").toString();
            }
            if (userInfo.containsKey("gender") && userInfo.get("gender") != null) {
                gender = Integer.parseInt(userInfo.get("gender").toString());
            }
        }
        
        log.info("微信用户信息: {}", userInfo);
        
        try {
            // 基础验证
            if (!StringUtils.hasText(code)) {
                log.error("微信登录失败: code参数为空");
                return RestApiResponse.businessError("50001", "微信登录失败: code参数不能为空");
            }
            
            // 调用微信登录服务
            Map<String, Object> loginResult = wechatService.login(code);
            
            // 调试信息：输出完整的登录结果
            log.info("微信登录成功，结果: {}", loginResult);
            
            // 确保返回有用户ID和token
            if (loginResult == null || !loginResult.containsKey("userId") || !loginResult.containsKey("token")) {
                log.error("微信登录失败: 返回结果缺少必要信息 - {}", loginResult);
                
                // 尝试强制修复：如果有其中一个字段，但没有另一个，尝试补充
                if (loginResult != null) {
                    if (!loginResult.containsKey("userId") && loginResult.containsKey("id")) {
                        loginResult.put("userId", loginResult.get("id"));
                        log.info("已从id字段补充userId字段");
                    }
                    if (!loginResult.containsKey("token") && loginResult.containsKey("access_token")) {
                        loginResult.put("token", loginResult.get("access_token"));
                        log.info("已从access_token字段补充token字段");
                    }
                    
                    // 再次检查是否有必要字段
                    if (loginResult.containsKey("userId") && loginResult.containsKey("token")) {
                        log.info("字段补充成功，继续处理");
                        return RestApiResponse.ok("微信登录成功", loginResult);
                    }
                }
                
                return RestApiResponse.businessError("50001", "微信登录失败: 服务器返回数据不完整");
            }
            
            // 返回标准格式响应
            return RestApiResponse.ok("微信登录成功", loginResult);
        } catch (ApiException e) {
            log.error("微信登录异常: {}", e.getMessage(), e);
            return RestApiResponse.businessError(
                    String.valueOf(e.getErrorCode()), 
                    "微信登录失败: " + e.getMessage());
        } catch (Exception e) {
            log.error("微信登录异常: {}", e.getMessage(), e);
            return RestApiResponse.businessError(
                    String.valueOf(ResultCode.WECHAT_LOGIN_FAILED.getCode()), 
                    "微信登录失败: " + e.getMessage());
        }
    }

    /**
     * 微信手机号登录接口
     */
    @Operation(summary = "微信手机号登录", description = "使用微信获取的手机号进行登录")
    @PostMapping("/login/phone")
    public RestApiResponse<Map<String, Object>> loginWithPhone(
            @Parameter(description = "微信授权码") @RequestParam(required = false) String code,
            @Parameter(description = "加密数据") @RequestParam(required = false) String encryptedData,
            @Parameter(description = "加密向量") @RequestParam(required = false) String iv,
            @RequestBody(required = false) Map<String, Object> requestBody,
            HttpServletRequest request
    ) {
        // 记录请求头和请求内容类型
        String contentType = request.getContentType();
        log.info("微信手机号登录请求 - Content-Type: {}", contentType);

        // 从请求体中获取参数（如果URL参数中未提供）
        if (requestBody != null) {
            log.info("检测到请求体数据: {}", requestBody);
            
            if (code == null && requestBody.containsKey("code")) {
                code = String.valueOf(requestBody.get("code"));
                log.info("从请求体获取code: {}", code);
            } else if (code == null && requestBody.containsKey("wxCode")) { // 替代名称
                code = String.valueOf(requestBody.get("wxCode"));
                log.info("从请求体wxCode字段获取code: {}", code);
            }
            
            if (encryptedData == null && requestBody.containsKey("encryptedData")) {
                encryptedData = String.valueOf(requestBody.get("encryptedData"));
                log.info("从请求体获取encryptedData, 长度: {}", encryptedData.length());
            } else if (encryptedData == null && requestBody.containsKey("encrypted_data")) { // 替代名称
                encryptedData = String.valueOf(requestBody.get("encrypted_data"));
                log.info("从请求体encrypted_data字段获取encryptedData, 长度: {}", encryptedData.length());
            }
            
            if (iv == null && requestBody.containsKey("iv")) {
                iv = String.valueOf(requestBody.get("iv"));
                log.info("从请求体获取iv, 长度: {}", iv.length());
            }
        }
        
        // 在请求体中找不到，尝试从普通表单请求中获取参数
        if (code == null) {
            code = request.getParameter("code");
            if (code != null) {
                log.info("从表单参数获取code: {}", code);
            }
        }
        
        if (encryptedData == null) {
            encryptedData = request.getParameter("encryptedData");
            if (encryptedData != null) {
                log.info("从表单参数获取encryptedData, 长度: {}", encryptedData.length());
            }
        }
        
        if (iv == null) {
            iv = request.getParameter("iv");
            if (iv != null) {
                log.info("从表单参数获取iv, 长度: {}", iv.length());
            }
        }
        
        log.info("微信手机号登录请求 - code: {}", code);
        log.info("微信手机号登录请求 - encryptedData长度: {}", encryptedData != null ? encryptedData.length() : 0);
        log.info("微信手机号登录请求 - iv长度: {}", iv != null ? iv.length() : 0);
        
        try {
            // 基础验证
            if (!StringUtils.hasText(code)) {
                log.error("微信手机号登录失败: code参数为空");
                log.error("请求体数据: {}", requestBody);
                return RestApiResponse.businessError("50001", "微信登录失败: code参数不能为空");
            }
            
            if (!StringUtils.hasText(encryptedData) || !StringUtils.hasText(iv)) {
                log.error("微信手机号登录失败: 加密数据或IV为空, encryptedData={}, iv={}", 
                          encryptedData != null ? "长度:" + encryptedData.length() : "null", 
                          iv != null ? "长度:" + iv.length() : "null");
                log.error("请求体数据: {}", requestBody);
                return RestApiResponse.businessError("50002", "微信登录失败: 加密数据不完整");
            }
            
            // ✅ 检查是否来自公众号并获取相关信息
            boolean fromOfficialAccount = false;
            String officialAccountOpenid = null;
            Integer launchScene = null;
            
            if (requestBody != null) {
                if (requestBody.containsKey("fromOfficialAccount")) {
                    fromOfficialAccount = Boolean.TRUE.equals(requestBody.get("fromOfficialAccount"));
                    log.info("检测到来自公众号: {}", fromOfficialAccount);
                }
                
                if (requestBody.containsKey("officialAccountOpenid")) {
                    officialAccountOpenid = String.valueOf(requestBody.get("officialAccountOpenid"));
                    log.info("获取到公众号openid: {}", officialAccountOpenid);
                }
                
                if (requestBody.containsKey("launchScene")) {
                    try {
                        launchScene = Integer.valueOf(String.valueOf(requestBody.get("launchScene")));
                        log.info("获取到启动场景值: {}", launchScene);
                    } catch (NumberFormatException e) {
                        log.warn("启动场景值格式不正确: {}", requestBody.get("launchScene"));
                    }
                }
            }
            
            // 调用微信手机号登录服务
            Map<String, Object> loginResult = wechatService.loginWithPhone(code, encryptedData, iv);
            
            // ✅ 如果来自公众号且有公众号openid，尝试绑定公众号
            if (fromOfficialAccount && StringUtils.hasText(officialAccountOpenid) && loginResult != null) {
                try {
                    Object userIdObj = loginResult.get("userId");
                    if (userIdObj != null) {
                        Long userId = Long.valueOf(String.valueOf(userIdObj));
                        log.info("尝试为用户 {} 绑定公众号openid: {}", userId, officialAccountOpenid);
                        
                        // 调用绑定公众号的服务
                        boolean bindResult = wechatService.bindOfficialAccountToUser(userId, officialAccountOpenid);
                        if (bindResult) {
                            log.info("公众号绑定成功: userId={}, officialOpenid={}", userId, officialAccountOpenid);
                            loginResult.put("officialAccountBound", true);
                            loginResult.put("message", "登录成功并已绑定公众号");
                        } else {
                            log.warn("公众号绑定失败: userId={}, officialOpenid={}", userId, officialAccountOpenid);
                            loginResult.put("officialAccountBound", false);
                        }
                    }
                } catch (Exception bindException) {
                    log.error("绑定公众号时发生异常", bindException);
                    // 绑定失败不影响登录流程
                    loginResult.put("officialAccountBound", false);
                    loginResult.put("bindError", bindException.getMessage());
                }
            }
            
            // 调试信息：输出完整的登录结果
            log.info("微信手机号登录成功，结果: {}", loginResult);
            
            // 确保返回有用户ID和token
            if (loginResult == null || !loginResult.containsKey("userId") || !loginResult.containsKey("token")) {
                log.error("微信手机号登录失败: 返回结果缺少必要信息 - {}", loginResult);
                
                // 尝试强制修复：如果有其中一个字段，但没有另一个，尝试补充
                if (loginResult != null) {
                    if (!loginResult.containsKey("userId") && loginResult.containsKey("id")) {
                        loginResult.put("userId", loginResult.get("id"));
                        log.info("已从id字段补充userId字段");
                    }
                    if (!loginResult.containsKey("token") && loginResult.containsKey("access_token")) {
                        loginResult.put("token", loginResult.get("access_token"));
                        log.info("已从access_token字段补充token字段");
                    }
                    
                    // 再次检查是否有必要字段
                    if (loginResult.containsKey("userId") && loginResult.containsKey("token")) {
                        log.info("字段补充成功，继续处理");
                        return RestApiResponse.ok("微信手机号登录成功", loginResult);
                    }
                }
                
                return RestApiResponse.businessError("50001", "微信手机号登录失败: 服务器返回数据不完整");
            }
            
            // 返回标准格式响应
            return RestApiResponse.ok("微信手机号登录成功", loginResult);
        } catch (ApiException e) {
            log.error("微信手机号登录异常: {}", e.getMessage(), e);
            return RestApiResponse.businessError(
                    String.valueOf(e.getErrorCode()), 
                    "微信手机号登录失败: " + e.getMessage());
        } catch (Exception e) {
            log.error("微信手机号登录异常: {}", e.getMessage(), e);
            return RestApiResponse.businessError(
                    String.valueOf(ResultCode.WECHAT_LOGIN_FAILED.getCode()), 
                    "微信手机号登录失败: " + e.getMessage());
        }
    }

    /**
     * 更新用户微信信息
     */
    @Operation(summary = "更新微信用户信息", description = "更新已登录用户的微信相关信息")
    @PutMapping("/user-info")
    public RestApiResponse<Boolean> updateUserInfo(
            @Parameter(description = "用户ID") @RequestParam Long userId,
            @Parameter(description = "昵称") @RequestParam(required = false) String nickname,
            @Parameter(description = "头像") @RequestParam(required = false) String avatar,
            @Parameter(description = "性别") @RequestParam(required = false) Integer gender
    ) {
        boolean result = wechatService.updateUserInfo(userId, nickname, avatar, gender);
        return RestApiResponse.ok("用户信息更新成功", result);
    }

    /**
     * 绑定微信账号
     */
    @Operation(summary = "绑定微信账号", description = "将已有账号与微信账号进行绑定")
    @PostMapping("/bind")
    public RestApiResponse<Boolean> bindWechat(
            @Parameter(description = "用户ID") @RequestParam Long userId,
            @Parameter(description = "微信授权码") @RequestParam String code
    ) {
        boolean result = wechatService.bindWechat(userId, code);
        return RestApiResponse.ok("微信账号绑定成功", result);
    }

    /**
     * 解绑微信账号
     */
    @Operation(summary = "解绑微信账号", description = "解除已绑定的微信账号")
    @PostMapping("/unbind")
    public RestApiResponse<Boolean> unbindWechat(
            @Parameter(description = "用户ID") @RequestParam Long userId
    ) {
        boolean result = wechatService.unbindWechat(userId);
        return RestApiResponse.ok("微信账号解绑成功", result);
    }

    /**
     * 测试发送订阅消息
     */
    @Operation(summary = "测试发送订阅消息", description = "测试发送订阅消息功能")
    @PostMapping("/subscribe/test-message")
    public RestApiResponse<Boolean> testSendMessage(@Parameter(description = "用户ID") @RequestParam Long userId) {
        try {
            log.info("=== 开始测试发送订阅消息 ===");
            log.info("测试发送订阅消息: userId={}", userId);
            
            // 先验证用户信息
            User user = userService.getById(userId);
            if (user == null) {
                log.error("测试失败: 用户不存在, userId={}", userId);
                return RestApiResponse.businessError("50006", "用户不存在");
            }
            
            log.info("用户验证通过: id={}, openid={}, nickname={}", 
                    user.getId(), user.getOpenid(), user.getNickname());
            
            if (!StringUtils.hasText(user.getOpenid())) {
                log.error("测试失败: 用户未绑定微信, userId={}", userId);
                return RestApiResponse.businessError("50006", "用户未绑定微信");
            }
            
            // 验证微信配置
            log.info("验证微信配置...");
            try {
                String accessToken = wxMaService.getAccessToken();
                log.info("微信AccessToken获取成功: {}", accessToken != null ? "已获取" : "获取失败");
            } catch (Exception e) {
                log.error("微信AccessToken获取失败", e);
                return RestApiResponse.businessError("50006", "微信配置错误: " + e.getMessage());
            }
            
            // 模拟测试成功（因为已经移除了实际发送功能）
            log.info("=== 测试结果: 成功（模拟） ===");
            return RestApiResponse.ok("测试消息发送成功（模拟）", true);
            
        } catch (Exception e) {
            log.error("测试发送订阅消息异常: userId={}", userId, e);
            return RestApiResponse.businessError("50006", "测试发送消息异常: " + e.getMessage());
        }
    }

    /**
     * 获取公众号授权URL
     */
    @Operation(summary = "获取公众号授权URL", description = "获取微信公众号授权链接")
    @PostMapping("/auth/get-auth-url")
    public RestApiResponse<String> getAuthUrl() {
        try {
            String authUrl = generateOfficialAccountAuthUrl();
            return RestApiResponse.ok("获取授权URL成功", authUrl);
        } catch (Exception e) {
            log.error("获取授权URL失败", e);
            return RestApiResponse.businessError("50001", "获取授权URL失败: " + e.getMessage());
        }
    }

    /**
     * 生成公众号授权URL
     */
    private String generateOfficialAccountAuthUrl() {
        // 这里应该生成微信公众号的授权URL
        // 由于目前缺少公众号的appid等配置，返回一个占位URL
        return "https://open.weixin.qq.com/connect/oauth2/authorize?appid=YOUR_APPID&redirect_uri=YOUR_CALLBACK_URL&response_type=code&scope=snsapi_userinfo&state=STATE";
    }

    /**
     * 获取当前登录用户的基础信息接口
     * 提供给前端用于判断是否已登录等
     */
    @Operation(summary = "获取当前用户信息", description = "获取当前登录用户的基础信息")
    @GetMapping("/user/info")
    public RestApiResponse<Map<String, Object>> getCurrentUserInfo(HttpServletRequest request) {
        try {
            // 从请求头中获取用户ID（由JWT过滤器设置）
            Long userId = (Long) request.getAttribute("userId");
            if (userId == null) {
                return RestApiResponse.unauthorized("用户未登录");
            }
            
            // 获取用户信息
            User user = userService.getById(userId);
            if (user == null) {
                return RestApiResponse.businessError("50001", "用户不存在");
            }
            
            // 构建返回数据
            Map<String, Object> userInfo = new HashMap<>();
            userInfo.put("userId", user.getId());
            userInfo.put("username", user.getNickname()); // 使用nickname作为username
            userInfo.put("nickname", user.getNickname());
            userInfo.put("phone", user.getPhone());
            userInfo.put("avatar", user.getAvatar());
            
            return RestApiResponse.ok("获取用户信息成功", userInfo);
            
        } catch (Exception e) {
            log.error("获取用户信息失败", e);
            return RestApiResponse.businessError("50001", "获取用户信息失败: " + e.getMessage());
        }
    }

    /**
     * 绑定公众号到用户
     */
    @Operation(summary = "绑定公众号", description = "将微信公众号绑定到当前用户")
    @PostMapping("/bind/official-account")
    public RestApiResponse<Map<String, Object>> bindOfficialAccount(
            @RequestBody Map<String, Object> requestBody,
            HttpServletRequest request) {
        try {
            // 获取当前登录用户ID
            Long userId = (Long) request.getAttribute("userId");
            if (userId == null) {
                return RestApiResponse.unauthorized("用户未登录");
            }

            // 获取公众号openid
            String officialAccountOpenid = null;
            if (requestBody != null && requestBody.containsKey("officialAccountOpenid")) {
                officialAccountOpenid = String.valueOf(requestBody.get("officialAccountOpenid"));
            }

            if (!StringUtils.hasText(officialAccountOpenid)) {
                return RestApiResponse.businessError("50001", "公众号openid不能为空");
            }

            log.info("绑定公众号请求: userId={}, officialAccountOpenid={}", userId, officialAccountOpenid);

            // 调用绑定服务
            boolean bindResult = wechatService.bindOfficialAccountToUser(userId, officialAccountOpenid);

            if (bindResult) {
                Map<String, Object> result = new HashMap<>();
                result.put("success", true);
                result.put("message", "公众号绑定成功");
                result.put("userId", userId);
                result.put("officialAccountOpenid", officialAccountOpenid);

                log.info("公众号绑定成功: userId={}, officialAccountOpenid={}", userId, officialAccountOpenid);
                return RestApiResponse.ok("公众号绑定成功", result);
            } else {
                log.warn("公众号绑定失败: userId={}, officialAccountOpenid={}", userId, officialAccountOpenid);
                return RestApiResponse.businessError("50002", "公众号绑定失败，可能已被其他用户使用");
            }

        } catch (Exception e) {
            log.error("绑定公众号异常", e);
            return RestApiResponse.businessError("50001", "绑定公众号失败: " + e.getMessage());
        }
    }
} 